package com.sx.mvvmlibs.utils

import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import android.os.Message
import android.util.Log
import com.blankj.utilcode.util.AppUtils
import java.io.BufferedWriter
import java.io.FileOutputStream
import java.io.OutputStreamWriter
import java.text.SimpleDateFormat
import java.util.*
import com.sx.mvvmlibs.config.GlobalConfig

/**
 * @Author: YY
 * @Date: 2022/1/5
 * @Describe: 日志输出工具类
 */
object Logs {

    /**
     * 是否强制输出日志
     */
    var mIsForceLog = false

    // 只有 debug 和 beta 才默认输出 log
    private val mIsLog: Boolean =  GlobalConfig.gIsSaveLog

    fun isLog() = mIsForceLog || mIsLog

    // 类名
    private var className: String? = null
    // 方法名
    private var methodName: String? = null
    // 行数
    private var lineNumber = 0

    // 日志类型
    private const val V = 0x1
    private const val D = 0x2
    private const val I = 0x3
    private const val W = 0x4
    private const val E = 0x5
    private const val A = 0x6

    private lateinit var mHandler: Handler

    private lateinit var mBufferWrite: BufferedWriter

    private lateinit var mCurDateTime: String

    @JvmStatic
    fun v(msg: Any?) {
        printLog(V, null, msg)
    }

    @JvmStatic
    fun v(tag: String?, msg: String?) {
        printLog(V, tag, msg)
    }

    @JvmStatic
    fun d(msg: Any?) {
        printLog(D, null, msg)
    }

    @JvmStatic
    fun d(tag: String?, msg: Any?) {
        printLog(D, tag, msg)
    }

    @JvmStatic
    fun i(msg: Any?) {
        printLog(I, null, msg)
    }

    @JvmStatic
    fun i(tag: String?, msg: Any?) {
        printLog(I, tag, msg)
    }

    @JvmStatic
    fun w(msg: Any?) {
        printLog(W, null, msg)
    }

    @JvmStatic
    fun w(tag: String?, msg: Any?) {
        printLog(W, tag, msg)
    }

    @JvmStatic
    fun e(msg: Any?) {
        printLog(E, null, msg)
    }

    @JvmStatic
    fun e(tag: String?, msg: Any?) {
        printLog(E, tag, msg)
    }

    @JvmStatic
    fun a(msg: Any?) {
        printLog(A, null, msg)
    }

    @JvmStatic
    fun a(tag: String?, msg: Any?) {
        printLog(A, tag, msg)
    }


    /**
     * 打印日志
     */
    private fun printLog(type: Int, tagStr: String?, objectMsg: Any?) {
        if (!isLog()) {
            return
        }
        val stackTrace = Thread.currentThread().stackTrace
        className = stackTrace[4].fileName
        methodName = stackTrace[4].methodName
        lineNumber = stackTrace[4].lineNumber

        val tag = tagStr ?: className

        methodName.let {
            // 针对Lambda表达式做个截取
            if (it!!.contains("$")) {
                val list = it.split("$")
                list.also {
                    methodName = list[0]
                }
            } else {
                it.substring(0, 1).uppercase(Locale.getDefault()) + it.substring(1)
            }
        }

        // 格式
        val buffer = StringBuilder()
        buffer.append("[(")
            .append(className).append(":")
            .append(lineNumber).append(")#")
            .append(methodName).append("] ")

        val msg = objectMsg?.toString() ?: "带有空对象的日志"
        buffer.append(msg)

        // 打印日志
        val logStr = buffer.toString()
        when (type) {
            V -> Log.v(tag, logStr)
            D -> Log.d(tag, logStr)
            I -> Log.i(tag, logStr)
            W -> Log.w(tag, logStr)
            E -> Log.e(tag, logStr)
            A -> Log.wtf(tag, logStr)
        }

        // 是否保存到本地缓存目录
        if (!this::mHandler.isInitialized && GlobalConfig.gIsSaveLog) {
            initLogHandler()
        }

        // 已初始化，则可以发送消息了
        if (this::mHandler.isInitialized) {
            val m = Message.obtain()
            m.obj = "$tag = $logStr"
            mHandler.sendMessage(m)
        }
    }

    /**
     * 初始化日志处理
     */
    private fun initLogHandler() {
        if (this::mHandler.isInitialized) {
            return
        }

        val handlerThread = HandlerThread("logbook")
        handlerThread.start()

        mCurDateTime = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date())
        mBufferWrite = BufferedWriter(
            OutputStreamWriter(
                FileOutputStream(FileTools.appLogDir + mCurDateTime + ".log", true)
            )
        )
        mBufferWrite.write(getDeviceInfo())


        mHandler = object : Handler(handlerThread.looper) {

            override fun handleMessage(msg: Message) {
                val dateTime = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date())
                if (dateTime != mCurDateTime) {
                    if (this@Logs::mBufferWrite.isInitialized) {
                        mBufferWrite.close()
                    }
                    mCurDateTime = dateTime
                    mBufferWrite = BufferedWriter(
                        OutputStreamWriter(FileOutputStream(
                            FileTools.appLogDir + mCurDateTime + ".log", true)
                        )
                    )
                    mBufferWrite.write(getDeviceInfo())
                }

                mBufferWrite.write(SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS",
                    Locale.getDefault()).format(Date()) + "/" + msg.obj.toString())
                mBufferWrite.newLine()
                mBufferWrite.flush()
            }
        }
    }

    /**
     * 设备信息
     */
    private fun getDeviceInfo(): String {
        val lineSeparator = "\r\n"
        val sb = StringBuilder()
        sb.append(lineSeparator)

        sb.append("appVerName:").append(AppUtils.getAppVersionName()).append(lineSeparator)
        sb.append("appVerCode:").append(AppUtils.getAppVersionCode()).append(lineSeparator)

        // 系统版本
        sb.append("OsVer:").append(Build.VERSION.RELEASE).append(lineSeparator)
        // 手机厂商
        sb.append("vendor:").append(Build.MANUFACTURER).append(lineSeparator)
        // 型号
        sb.append("model:").append(Build.MODEL).append(lineSeparator)
        sb.append(lineSeparator)
        sb.append(lineSeparator)
        return sb.toString()
    }

}